﻿//--------------------------- Multi-thread Upload Demo ---------------------------------------

//--------------------------------------------------------------------------------------------

//---File:          frmUpload

//---Description:   The multi-thread upload form file to demenstrate howto use multi-thread to 

//                  upload files

//---Author:        Knight

//---Date:          Oct.12, 2006

//--------------------------------------------------------------------------------------------

//---------------------------{Multi-thread Upload Demo}---------------------------------------

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace CSUpload
{

using System.IO;
using System.Diagnostics;
using System.Threading;
using Web References;     //Web-service reference namespace





//
    /// <summary>

    /// Summary description for Form1.

    /// </summary>

    public class frmUpload : System.Windows.Forms.Form
    {

        private System.Windows.Forms.TextBox txtFileName;
        private System.Windows.Forms.Button btnBrowse;
        private System.Windows.Forms.Button btnUpload;

        /// <summary>

        /// Required designer variable.

        /// </summary>

        private System.ComponentModel.Container components = null;
        public frmUpload()
        {

            //

            // Required for Windows Form Designer support

            //

            InitializeComponent();



            //

            // TODO: Add any constructor code after InitializeComponent call

            //

        }



        /// <summary>

        /// Clean up any resources being used.

        /// </summary>

        protected override void Dispose(bool disposing)
        {

            if (disposing)
            {

                if (components != null)
                {

                    components.Dispose();

                }

            }

            base.Dispose(disposing);

        }



        #region Windows Form Designer generated code

        /// <summary>

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary>

        private void InitializeComponent()
        {
            this.txtFileName = new System.Windows.Forms.TextBox();
            this.btnBrowse = new System.Windows.Forms.Button();
            this.btnUpload = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // txtFileName
            // 
            this.txtFileName.Location = new System.Drawing.Point(19, 26);
            this.txtFileName.Name = "txtFileName";
            this.txtFileName.Size = new System.Drawing.Size(298, 21);
            this.txtFileName.TabIndex = 0;
            // 
            // btnBrowse
            // 
            this.btnBrowse.Location = new System.Drawing.Point(326, 26);
            this.btnBrowse.Name = "btnBrowse";
            this.btnBrowse.Size = new System.Drawing.Size(90, 25);
            this.btnBrowse.TabIndex = 1;
            this.btnBrowse.Text = "&Browse...";
            this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);
            // 
            // btnUpload
            // 
            this.btnUpload.Location = new System.Drawing.Point(326, 60);
            this.btnUpload.Name = "btnUpload";
            this.btnUpload.Size = new System.Drawing.Size(90, 25);
            this.btnUpload.TabIndex = 2;
            this.btnUpload.Text = "&Upload";
            this.btnUpload.Click += new System.EventHandler(this.btnUpload_Click);
            // 
            // frmUpload
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
            this.ClientSize = new System.Drawing.Size(430, 112);
            this.Controls.Add(this.btnUpload);
            this.Controls.Add(this.btnBrowse);
            this.Controls.Add(this.txtFileName);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.Name = "frmUpload";
            this.Text = "Upload";
            this.Load += new System.EventHandler(this.frmUpload_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion



        //private FileUpload myUpload = new FileUpload();

        private void UploadData(string FileName, int StartPos, byte[] bData)
        {

            //Call web service upload

            WSUploadFile.UploadFileData(FileName, StartPos, bData);

        }



        private void btnUpload_Click(object sender, System.EventArgs e)
        {

            FileInfo fi = new FileInfo(txtFileName.Text);

            if (fi.Exists)
            {

                btnUpload.Enabled = false;//Avoid upload twice



                //Init signals

                ManualResetEvent[] events = new ManualResetEvent[5];



                //Devide blocks

                int nTotalBytes = (int)(fi.Length / 5);

                for (int i = 0; i < 5; i++)
                {

                    events[i] = new ManualResetEvent(false);

                    FileThread thdSub = new FileThread(

                        i * nTotalBytes,

                        (fi.Length - i * nTotalBytes) > nTotalBytes ? nTotalBytes : (int)(fi.Length - i * nTotalBytes),

                        fi.FullName);

                    ThreadPool.QueueUserWorkItem(new WaitCallback(thdSub.UploadFile), events[i]);

                }



                //Wait for threads finished

                WaitHandle.WaitAll(events);



                //Reset button status

                btnUpload.Enabled = true;

            }



        }



        private void frmUpload_Load(object sender, System.EventArgs e)
        {

            FileThread.UploadHandle = new UploadFileData(this.UploadData);

        }



        private void btnBrowse_Click(object sender, System.EventArgs e)
        {

            if (fileOpen.ShowDialog() == DialogResult.OK)

                txtFileName.Text = fileOpen.FileName;

        }

        private OpenFileDialog fileOpen = new OpenFileDialog();

    }



    public delegate void UploadFileData(string FileName, int StartPos, byte[] bData);



    /// <summary>

    /// FileThread: a class for sub-thread

    /// </summary>

    sealed class FileThread
    {

        private int nStartPos;

        private int nTotalBytes;

        private string strFileName;

        public static UploadFileData UploadHandle;



        /// <summary>

        /// Constructor

        /// </summary>

        /// <param name="StartPos"></param>

        /// <param name="TotalBytes"></param>

        /// <param name="FileName"></param>

        public FileThread(int StartPos, int TotalBytes, string FileName)
        {

            //Init thread variant

            nStartPos = StartPos;

            nTotalBytes = TotalBytes;

            strFileName = FileName;



            //Only for debug

            Debug.WriteLine(string.Format("File name:{0} position: {1} total byte:{2}",

                strFileName, nStartPos, nTotalBytes));

        }



        /// <summary>

        /// Sub-thread entry function 

        /// </summary>

        /// <param name="stateinfo"></param>

        public void UploadFile(object stateinfo)
        {

            int nRealRead, nBufferSize;

            const int BUFFER_SIZE = 10240;



            using (FileStream fs = new FileStream(strFileName,

                       FileMode.Open, FileAccess.Read,

                       FileShare.Read))
            {

                string sName = strFileName.Substring(strFileName.LastIndexOf("//") + 1);

                byte[] bBuffer = new byte[BUFFER_SIZE];//Init 10k buffer

                fs.Position = nStartPos;

                nRealRead = 0;

                do
                {

                    nBufferSize = BUFFER_SIZE;

                    if (nRealRead + BUFFER_SIZE > nTotalBytes)

                        nBufferSize = nTotalBytes - nRealRead;



                    nBufferSize = fs.Read(bBuffer, 0, nBufferSize);

                    if (nBufferSize == BUFFER_SIZE)

                        UploadHandle(sName,

                            nRealRead + nStartPos,

                            bBuffer);

                    else if (nBufferSize > 0)
                    {

                        //Copy data 

                        byte[] bytData = new byte[nBufferSize];

                        Array.Copy(bBuffer, 0, bytData, 0, nBufferSize);



                        UploadHandle(sName,

                            nRealRead + nStartPos,

                            bytData);

                    }



                    nRealRead += nBufferSize;

                }

                while (nRealRead < nTotalBytes);

            }

            //Release signal

            ManualResetEvent mr = stateinfo as ManualResetEvent;

            if (mr != null)

                mr.Set();

        }

    }



}

